home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-04 / bipl.zip / PROCS.ZIP / DATETIME.ICN < prev    next >
Text File  |  1992-09-28  |  9KB  |  301 lines

  1. ############################################################################
  2. #
  3. #    File:     datetime.icn
  4. #
  5. #    Subject:  Procedures for date manipulation
  6. #
  7. #    Author:   Robert J. Alexander
  8. #
  9. #    Date:     May 18, 1992
  10. #
  11. ###########################################################################
  12. #
  13. #  This set of procedures facilitates conversion of dates among several
  14. #  different date formats.  Dates and times can be converted to and from
  15. #  pure seconds past a standard point in time, thus date and time
  16. #  computations can be easily done as integer arithmetic.
  17. #
  18. #
  19. #  DateBaseYear and HoursFromGmt
  20. #  -----------------------------
  21. #  Some of these procedures convert to and from the number of seconds
  22. #  past the start of a base year.  Several operating systems use this as
  23. #  a standard technique for storing dates, but the base year varies from
  24. #  system to system.  Environment variable "DateBaseYear" allows
  25. #  specification of the base year.  If the environment variable
  26. #  "DateBaseYear" is undefined, the UNIX standard of 1970 is used.
  27. #
  28. #  Some of these routines convert from a standard world time format in
  29. #  which times are stored as universal coordinated time (UTC, or
  30. #  commonly known by its older name, GMT).  To convert to local time it
  31. #  is necessary to know the number of hours from GMT to the local time.
  32. #  For example, PST is -8 hours from GMT, and PDT is -7 hours.  Some of
  33. #  the procedures here have an "hoursFromGmt" argument.  An environment
  34. #  variable "HoursFromGmt" can be used to provide a default for an
  35. #  installation.
  36. #
  37. #
  38. #  The procedures are:
  39. #
  40. #  SecToDateRec(sec,hoursFromGmt)
  41. #  Produces a date record computed from the seconds since the start of
  42. #  DateBaseYear.
  43. #
  44. #  DateRecToSec(dateRec,hoursFromGmt)
  45. #  Converts a DateRec to seconds since start of DateBaseYear.
  46. #
  47. #  SecToDateLine(sec,hoursFromGmt)
  48. #  Produces a date in the same format as Icon's &dateline.
  49. #
  50. #  SecToUnixDate(sec,hoursFromGmt)
  51. #  Returns a date and time in typical UNIX format:  Jan 14 10:24 1991.
  52. #
  53. #  DateLineToSec(dateline,hoursFromGmt)
  54. #  Converts a date in &dateline format to seconds since start of
  55. #  DateBaseYear.
  56. #
  57. #  ClockToSec(s)
  58. #  Converts a time in the format of &clock to seconds past midnight.
  59. #
  60. #  SecToClock(i)
  61. #  Converts seconds past midnight to a string in the format of &clock.
  62. #
  63. #  DateToSec(s)
  64. #  Converts a date string in Icon &date format (yyyy/mm/dd) do seconds
  65. #  past DateBaseYear.
  66. #
  67. #  SecToDate(i)
  68. #  Converts seconds past DateBaseYear to a string in Icon &date format
  69. #  (yyyy/mm/dd).
  70. #
  71. ############################################################################
  72.  
  73. record DateRec(year,month,day,hour,min,sec,weekday)
  74.  
  75. global Months,Days,DateBaseYear
  76.  
  77. procedure DateInit()
  78. #
  79. #  Initialize the date globals -- done automatically by calls to date
  80. #  procedures.
  81. #
  82.    initial {
  83.       Months := ["January","February","March","April","May","June",
  84.         "July","August","September","October","November","December"]
  85.       Days := ["Sunday","Monday","Tuesday","Wednesday","Thursday",
  86.         "Friday","Saturday"]
  87.       /DateBaseYear := integer(getenv("DateBaseYear")) | 1970
  88.       }
  89.    return
  90. end
  91.  
  92.  
  93. procedure SecToDateRec(sec,hoursFromGmt)
  94. #
  95. #  Produces a date record computed from the seconds since the start of
  96. #  DateBaseYear.
  97. #
  98.    local day,hour,min,month,secs,weekday,year
  99.    initial DateInit()
  100.    sec := integer(sec) | runerr(101,sec)
  101.    /hoursFromGmt := getenv("HoursFromGmt") | 0
  102.    hoursFromGmt := integer(hoursFromGmt) | runerr(101,hoursFromGmt)
  103.    sec +:= hoursFromGmt * 3600
  104.    weekday := (sec / 86400 % 7 + 4) % 7 + 1
  105.    year := DateBaseYear
  106.    repeat {
  107.       secs := if year % 4 = 0 & year % 400 ~= 0 then 31622400 else 31536000
  108.       if sec < secs then break
  109.       year +:= 1
  110.       sec -:= secs
  111.       }
  112.    month := 1
  113.    every secs :=
  114.      2678400 |
  115.      (if year % 4 = 0 & year % 400 ~= 0 then 2505600 else 2419200) |
  116.      2678400 |
  117.      2592000 |
  118.      2678400 |
  119.      2592000 |
  120.      2678400 |
  121.      2678400 |
  122.      2592000 |
  123.      2678400 |
  124.      2592000 |
  125.      2678400 do {
  126.       if sec < secs then break
  127.       month +:= 1
  128.       sec -:= secs
  129.       }
  130.    day := sec / 86400 + 1
  131.    sec %:= 86400
  132.    hour := sec / 3600
  133.    sec %:= 3600
  134.    min := sec / 60
  135.    sec %:= 60
  136.    return DateRec(year,month,day,hour,min,sec,weekday)
  137. end
  138.  
  139.  
  140. procedure SecToDateLine(sec,hoursFromGmt)
  141. #
  142. #  Produces a date in the same format as Icon's &dateline.
  143. #
  144.    local d,hour,halfday
  145.    d := SecToDateRec(sec,hoursFromGmt)
  146.    if (hour := d.hour) < 12 then {
  147.       halfday := "am"
  148.       }
  149.    else {
  150.       halfday := "pm"
  151.       hour -:= 12
  152.       }
  153.    if hour = 0 then hour := 12
  154.    return Days[d.weekday] || ", " || Months[d.month] || " " || d.day ||
  155.      ", " || d.year || "  " || hour || ":" || right(d.min,2,"0") || " " ||
  156.      halfday
  157. end
  158.  
  159.  
  160. procedure SecToUnixDate(sec,hoursFromGmt)
  161. #
  162. #  Returns a date and time in UNIX format: Jan 14 10:24 1991
  163. #
  164.    local d
  165.    d := SecToDateRec(sec,hoursFromGmt)
  166.    return Months[d.month][1+:3] || " " || d.day || " " ||
  167.      d.hour || ":" || right(d.min,2,"0") || " " || d.year
  168. end
  169.  
  170.  
  171. procedure DateLineToSec(dateline,hoursFromGmt)
  172. #
  173. #  Converts a date in long form to seconds since start of DateBaseYear.
  174. #
  175.    local day,halfday,hour,min,month,sec,year
  176.    static months
  177.    initial {
  178.       DateInit()
  179.       months := table()
  180.       months["jan"] := 1
  181.       months["feb"] := 2
  182.       months["mar"] := 3
  183.       months["apr"] := 4
  184.       months["may"] := 5
  185.       months["jun"] := 6
  186.       months["jul"] := 7
  187.       months["aug"] := 8
  188.       months["sep"] := 9
  189.       months["oct"] := 10
  190.       months["nov"] := 11
  191.       months["dec"] := 12
  192.       }
  193.    map(dateline) ? {
  194.       tab(many(' \t'))
  195.       =("sun" | "mon" | "tue" | "wed" | "thu" | "fri" | "sat") &
  196.         tab(many(&letters)) | &null & tab(many(' \t,')) | &null
  197.       month := 1(tab(many(&letters)),tab(many('  \t')) | &null)
  198.       day <- integer(1(tab(many(&digits)),tab(many(' \t,')) | &null)) | &null &
  199.       year <- integer(1(tab(many(&digits)),tab(many(' \t')) | &null)) | &null &
  200.       (hour <- integer(tab(many(&digits))) &
  201.         ((=":" & min <- integer(tab(many(&digits)))) &
  202.         ((=":" & sec <- integer(tab(many(&digits)))) | &null) | &null) &
  203.         tab(many(' \t')) | &null & halfday := =("am" | "pm") | &null &
  204.         tab(many(' \t')) | &null) | &null & pos(0)
  205.       }
  206.    \month :=  \months[month[1+:3]] | fail
  207.    if not /(halfday | hour) then {
  208.       if hour = 12 then hour := 0
  209.       if halfday == "pm" then
  210.         hour +:= 12
  211.       }
  212.    return DateRecToSec(DateRec(year,month,day,hour,min,sec),hoursFromGmt)
  213. end
  214.  
  215.  
  216. procedure DateRecToSec(dateRec,hoursFromGmt)
  217. #
  218. #  Converts a DateRec to seconds since start of DateBaseYear.
  219. #
  220.    local day,hour,min,month,sec,secs,year,yr
  221.    static days
  222.    initial {
  223.       DateInit()
  224.       days := [
  225.      0,
  226.      2678400,
  227.      5097600,
  228.      7776000,
  229.      10368000,
  230.      13046400,
  231.      15638400,
  232.      18316800,
  233.      20995200,
  234.      23587200,
  235.      26265600,
  236.      28857600
  237.       ]
  238.       }
  239.    /hoursFromGmt := getenv("HoursFromGmt") | 0
  240.    hoursFromGmt := integer(hoursFromGmt) | runerr(101,hoursFromGmt)
  241.    year := \dateRec.year | +&date[1+:4]
  242.    month := \dateRec.month | +&date[6+:2]
  243.    day := \dateRec.day | +&date[9+:2]
  244.    hour := \dateRec.hour | 0
  245.    min := \dateRec.min | 0
  246.    sec := \dateRec.sec | 0
  247.    secs := 0
  248.    every yr := DateBaseYear to year - 1  do {
  249.       secs +:= if yr % 4 = 0 & yr % 400 ~= 0 then 31622400 else 31536000
  250.       }
  251.    if month > 2 & year % 4 = 0 & year % 400 ~= 0 then secs +:= 86400
  252.    return secs + days[month] + (day - 1) * 86400 +
  253.      (hour - hoursFromGmt) * 3600 + min * 60 + sec
  254. end
  255.  
  256.  
  257. procedure ClockToSec(s)
  258. #
  259. #  Converts a time in the format of &clock to seconds past midnight.
  260. #
  261.     s ? return (
  262.      (1(tab(many(&digits)),move(1)) * 60 +
  263.      1(tab(many(&digits)),move(1) | &null)) * 60 +
  264.      (tab(many(&digits)) | 0)
  265.      )
  266. end
  267.  
  268.  
  269. procedure SecToClock(i)
  270. #
  271. #  Converts seconds past midnight to a string in the format of &clock.
  272. #
  273.     local sec
  274.     sec := i % 60
  275.     i /:= 60
  276.     return right(i / 60,2,"0") || ":" || right(i % 60,2,"0") || ":" ||
  277.          right(sec,2,"0")
  278. end
  279.  
  280.  
  281. procedure DateToSec(s)
  282. #
  283. #  Converts a date in Icon &date format (yyyy/mm/dd) do seconds
  284. #  past DateBaseYear.
  285. #
  286.     s ? return DateRecToSec(DateRec(+1(tab(find("/")),move(1)),
  287.     +1(tab(find("/")),move(1)),+tab(0)))
  288. end
  289.  
  290.  
  291. procedure SecToDate(i)
  292. #
  293. #  Converts seconds past DateBaseYear to a &date in Icon date format
  294. #  (yyyy,mm,dd).
  295. #
  296.     local r
  297.     r := SecToDateRec(i)
  298.     return right(r.year,4,"0") || "/" || right(r.month,2,"0") || "/" ||
  299.          right(r.day,2,"0")
  300. end
  301.